﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

/**Class: EmployeePrefPerTimeSlot
 * @author:  Sara Tuohy
 * @version: 1.0
 * Course:  ITEC 4860
 * Written: March, 2012
 * Form for the employee to designate each open time slot as "A" (available), "N" (not available), 
 * or "P" (preferred)
 */
namespace Scheduler.Presentation_Layer
{
    public partial class EmployeePrefPerTimeSlot : Form
    {
        /**
         * Array of openHours passed in from calling panel                           */
        private String[] timeSlots;
        /**
         * Global ID of current user for storing his preferences                     */
        private string currentUser;
        /**
         * An array list for accessing the dynamically created combo boxes           */
        private ComboBox[] employeePreferences;
        /**
         * The day for which the employee is specifying his preferences              */
        private OperationDay theDay;
        /**
         * See if we can reuse saved data from DB                                    */
        private bool usingDBData;
        /**
         * Constant number of days in a week                                         */
        private const int NUM_WEEK_DAYS = 7;
        /**
         * Start time used in several code sections                                  */
        string startTime;
        /**
         * startTimeIdx and endTimeIdx also used to set up combo boxes               */
        int startTimeIdx;
        /**
         * startTimeIdx and endTimeIdx also used to set up combo boxes               */
        int endTimeIdx;
        /**
         * Holds the preferences read from the DB to set up combo boxes              */
        object[] empDayPrefs;

        /**Method: EmployeePrefPerTimeSlot
         * Constructor
         * @param string[] times, the hours of operation
         * @param OperationDay opDay the day in question
         */
        public EmployeePrefPerTimeSlot(string[] times, OperationDay opDay)
        {
            timeSlots = times;
            theDay = opDay;
            usingDBData = false;
            InitializeComponent();
            setDayLabel();
            employeePreferences = new ComboBox[timeSlots.Length];
            currentUser = Presentation_Layer.GlobalVariables.GlobalLoggedInUser;
            startTime = timeSlots[0];
            startTimeIdx = Array.IndexOf(GlobalVariables.GlobalAllTimeSlots, startTime);
            endTimeIdx = Array.IndexOf(GlobalVariables.GlobalAllTimeSlots, timeSlots[timeSlots.Length - 1]);
            //Correction 04/12 - the save to DB (and subsequent restore) was off by one  
            //(Due to the "" in slot 00 of AllTimeSlots).  Make a one time correction here ...
            startTimeIdx--;
            endTimeIdx--;
            checkDB();
            formatTable();
        }

        /**Method: checkDB
         * Compare timestamp for when "hours of operation" were last saved with the last save
         * of employee preferences, and if the preferences is newer, load them from the DB
         * Otherwise errors are caused by the hours mismatch; toss all preferences and start fresh.
         * Sets global "usingDBData"
         */
        private void checkDB()
        {
            Data_Access_Layer.EmpDayInfo employeeDay;

            if (true)
            {
                employeeDay = new Data_Access_Layer.EmpDayInfo(currentUser, theDay.getDayName());

                if (!employeeDay.locateEmpDay())
                {
                    employeeDay.createEmpDay(currentUser, theDay.getDayName());
                }
                if (employeeDay.locateEmpDay())
                {
                    empDayPrefs = (object[])employeeDay.getAllAvailHr();
                    if (!empDayPrefs[2].ToString().Equals(""))
                        usingDBData = true;
                }
            }
        }

        /**Method: setDayLabel
         * Labels the panel so the employee can see which day he is working with
         */
        private void setDayLabel()
        {
            string labelText = "Day: " + theDay.getDayName();
            dayIDLabel.Text = labelText;
        }

        /**Method: formatTable
         * Adds labels and combo boxes for each time slot of operation
         * Allows us to determine size at runtime
         */
        private void formatTable()
        {

            this.empPrefsPerSlotTabLayoutPan.ColumnCount = 2;
            int colZero = 0;
            int colOne = 1;
            for (int i = 0; i < timeSlots.Length; i++)
            {
                empPrefsPerSlotTabLayoutPan.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F));
                empPrefsPerSlotTabLayoutPan.Controls.Add(defineTableLabel(timeSlots[i], i), colZero, i);
                employeePreferences[i] = createPrefComboBox(i);
                empPrefsPerSlotTabLayoutPan.Controls.Add(employeePreferences[i], colOne, i);
            }
            empPrefsPerSlotTabLayoutPan.Controls.Add(defineTableLabel("", timeSlots.Length), colZero, timeSlots.Length);
        }

        /**Method: defineTableLabel
         * Use the time entries to format labels for the selection
         * @param string txt label text
         * @param int ctr counter used for tabbing
         * @return Label label for the table
         */
        private Label defineTableLabel(String txt, int ctr)
        {
            Label newLabel = new System.Windows.Forms.Label();
            newLabel.AutoSize = true;
            //Anchor property is how it is situated within the TableLayoutPanel
            newLabel.Anchor = AnchorStyles.Left;
            newLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F,
                System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
                ((byte)(0)));
            newLabel.Visible = true;
            newLabel.Location = new System.Drawing.Point(3, 0);
            newLabel.Size = new System.Drawing.Size(43, 13);
            newLabel.Text = txt;
            return newLabel;
        }       //end of defineTableLabel

        /**Method: createPrefComboBox
         * Create combo boxes with selections of "A", "N", or "P" to 
         * indicate available, not available, and preferred time slots.
         * Update 04/10: if usingDBData, set the combobox selected index 
         * to the IndexOf value of a string == ANP.
         * @param int ctr counter used for tabbing
         * @return ComboBox for the layout panel
         */
        private ComboBox createPrefComboBox(int ctr)
        {
            string idxFinder = "ANP";
            ComboBox cb = new System.Windows.Forms.ComboBox();
            cb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            cb.Size = new System.Drawing.Size(35, 20);
            cb.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F,
                System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
                ((byte)(0)));
            cb.FormattingEnabled = true;
            //Anchor property is how it is situated within the TableLayoutPanel
            cb.Anchor = AnchorStyles.Left;
            cb.Items.AddRange(new object[] { "A", "N", "P" });
            if (usingDBData)
            {
                //here we correct the ordination of the empDayPrefs array, which has the day and empID in slots 0 and 1
                //then has all the times (00:00, 00:30, etc.) so we want to move ahead to start time ...
                int dbPtr = ctr + startTimeIdx + 2;
                string pref = "";
                if (dbPtr < empDayPrefs.Length)
                {
                    pref = empDayPrefs[dbPtr].ToString().Trim();
                    cb.SelectedIndex = idxFinder.IndexOf(pref);
                }
                else
                {
                    cb.SelectedIndex = 0;
                }
            }
            else
            {
                cb.SelectedIndex = 0;
            }
            cb.TabIndex = ctr;
            return cb;
        }

        /**Method: cancelButton_Click
         * Return to calling panel
         */
        private void cancelButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /**Method: saveButton_Click
         * Call storeValidData to store in the DB
         */
        private void saveButton_Click(object sender, EventArgs e)
        {
            storeValidData();
        }

        /**Method storeValidData()
         * Gets an array to save to the DB
         * Update 04/20: save "Today" to the EmployeeTable preferences updated table.
         */
        private void storeValidData()
        {
            object[] employeeDayData = null;
            Data_Access_Layer.EmpDayInfo employeeDay;
            int idx = Array.IndexOf(GlobalVariables.GlobalWeekDays, theDay.getDayName());
            employeeDay = new Data_Access_Layer.EmpDayInfo(currentUser, GlobalVariables.GlobalWeekDays[idx]);

            if (!employeeDay.locateEmpDay())
            {
                employeeDay.createEmpDay(currentUser, GlobalVariables.GlobalWeekDays[idx]);
            }
            if (employeeDay.locateEmpDay())
            {
                employeeDayData = createObjectArrayWork(true);
                employeeDay.setAllAvailHr(employeeDayData);
                string currentDateTime = GlobalVariables.GlobalCurrentDateTime;
                Data_Access_Layer.Employee employeeData = new Data_Access_Layer.Employee(currentUser);
                if (employeeData.locateEmployee())
                {
                    employeeData.setPreferencesLastUpdated(currentDateTime);
                    MessageBox.Show("Saved Working day: " + GlobalVariables.GlobalWeekDays[idx],
                        "DB Updated", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    employeeData.setPreferencesLastUpdated(currentDateTime);
                    MessageBox.Show("Locate failed for " + currentUser,
                        "DB Update Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("Error locating Employee Day", "Day Locate Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        /**Method: createObjectArrayWork
        * This method gathers the information needed for input to the "setAllAvailHr" database method
        * The array cells contain the following (in order): day, empID, 
        * and 48 time slots of string.  We must set all of these to "A" (the default) *except* when he has 
        * selected "N" or "P".
        * @return object[] with the needed data
        */
        private object[] createObjectArrayWork(bool isOpen)
        {
            object[] empDay = new object[50];
            empDay[0] = theDay.getDayName();
            empDay[1] = currentUser;

            if (isOpen)
            {
                int comparableI = 0;
                int prefListIdx = 0;
                //this would not be tricky if the index started at 0, but it starts at 2 ...
                for (int i = 2; i < empDay.Length; i++)
                {
                    comparableI = i - 2;

                    //slots before the start of day get the default
                    if (comparableI < startTimeIdx)
                    {
                        empDay[i] = "A";
                    }
                    //slots during working hours get the employee's selection
                    else if (comparableI <= endTimeIdx)
                    {
                        if (prefListIdx >= employeePreferences.Length)
                        {
                            MessageBox.Show("Attempting to Access Non-Existent Combo Box", "Program Logic Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                        else
                        {
                            empDay[i] = employeePreferences[prefListIdx].SelectedItem.ToString();
                            prefListIdx++;
                        }
                    }
                    //slots after the end of day get the default
                    else
                    {
                        empDay[i] = "A";
                    }

                }
            }
            else                                //else not open; set all the time slots to available ...  
            {
                for (int i = 2; i < empDay.Length; i++)
                {
                    empDay[i] = "A";
                }
            }
            return empDay;
        }
    }
}
